import { _decorator, Camera, Collider, Component, EventTouch, geometry, Input, input, isValid, Layers, Node, PhysicsSystem, RigidBody, tween, v3, Vec2, Vec3, Vec4, view } from 'cc';
import { eliminateGameManager } from './EliminateGameManager';
import { EliminateSlotTrigger, PhyGroup } from './EliminateSlotTrigger';
import { EliminateToy } from './EliminateToy';
import { Prefab } from 'cc';
import { instantiate } from 'cc';
import { Animation } from 'cc';
import { AnimationState } from 'cc';
import { AnimationClip } from 'cc';
import { Label } from 'cc';
import { isProd, splitVersionNum, tweenLabelString } from '../../common/util';
import { Button } from 'cc';
import { EliminateTopUI } from './EliminateTopUI';
import NDB from '../../common/NDBTS';
import { EliminateSlot } from './EliminateSlot';
import { eliminateConsts, EliminateMode } from './EliminateConst';
import CommonToastManager from '../../common/Toast/CommonToastManager';
import { EliminateResult } from './EliminateResult';
import { Sprite } from 'cc';
import { UIOpacity } from 'cc';
import { Tween } from 'cc';
import { audioManager } from '../../common/AudioManager';
import { JsonAsset } from 'cc';
import { RenderTexture } from 'cc';
import { SpriteFrame } from 'cc';
import { UITransform } from 'cc';
import { GamePreview } from './postProcess/GamePreview';
import { gfx } from 'cc';
import { EliminateMatch3Logic } from './EliminateMatch3Logic';
const { ccclass, property } = _decorator;

/**
 * 
 * 二消
 * 
 */
@ccclass('EliminateUIManager')
export class EliminateUIManager extends Component {
    @property(Camera)
    public camera: Camera = null;

    @property(JsonAsset)
    debugJson: JsonAsset = null;

    @property(Camera)
    public UICamera: Camera = null;
    @property(Camera)
    public toastCamera: Camera = null;

    @property(GamePreview)
    gamePreview: GamePreview = null;

    @property(EliminateSlot)
    slotsNode: EliminateSlot = null;

    @property(Prefab)
    pausePrefab: Prefab = null!;
    @property(Prefab)
    resultPrefab: Prefab = null!;

    @property(Node)
    slotNode: Node = null;

    @property(Node)
    doorRoot: Node = null;

    @property(Node)
    progressBg: Node = null;

    @property(Node)
    ring: Node = null;

    @property(Label)
    timesLabel: Label = null;
    @property(Label)
    scoreLabel: Label = null;

    @property(Label)
    toolTimesLabel: Label = null;

    @property(Label)
    levelNumberLabel: Label = null;

    // @property(Button)
    // toolButton: Button = null;

    @property(EliminateTopUI)
    topUI: EliminateTopUI = null;

    @property(Sprite)
    bg: Sprite = null;

    @property(Node)
    idea: Node = null;

    @property(Label)
    versionLable: Label = null;

    @property(EliminateMatch3Logic)
    match3: EliminateMatch3Logic = null;

    @property(Prefab)
    match3Pause: Prefab = null;

    @property(Node)
    match2: Node = null;

    private _dragging: boolean = false;
    public set dragging(value: boolean) {
        this._dragging = value;
    }
    public get dragging(): boolean {
        return this._dragging;
    }

    private _delta: Vec3 = new Vec3();

    public tapNode: Node = null;

    private moveEvent: EventTouch = null;

    private touchStartTime: number = 0;
    private touchEndTime: number = 0;

    private cameraHeight: number = 0;

    private startTime: number = 0;

    private moveCD: number = 0.01;
    private moveSend: boolean = true;

    private y: number = 15;

    private testOpen: boolean = true;

    private tapStartPos: Vec3 = v3(0);

    private matJsonData: { [key: string]: { name: string, mat_uuid: string, matName: string, scale: { x: number, y: number, z: number } } } = null;

    /** 手指移动过程中的路径点 */
    // private movePaths: Vec3[] = [];

    protected __preload(): void {
        // gameManager.uiManager = this;
        eliminateGameManager.uiManager = this;
    }

    protected onLoad(): void {
        this.adapterCamera();
        console.log("viewSize is ", view.getVisibleSize());
        this._initDebugVersionInfo();
        this.versionLable.node.active = !isProd();

        let isMatch2 = eliminateGameManager.gameMode == EliminateMode.MATCH2;

        this.match2.active = isMatch2;
        this.match3.node.active = !isMatch2;

        // this.slotNode.active = isMatch2;
        // this.slotNode.active = isMatch2;
    }

    private _initDebugVersionInfo() {
        const debugStr = this.debugJson.json['version'];
        this.versionLable.string = "V" + splitVersionNum(debugStr);

    }

    public transparentBg(tag: boolean) {
        const transComp = this.bg.node.getComponent(UIOpacity);
        if (tag) {
            transComp.opacity = 0;
        } else {
            transComp.opacity = 255;
        }
    }

    public adapterCamera() {

    }

    setRingNodePostion(pos: Vec3) {
        this.ring.setPosition(pos);
        this.progressBg.setPosition(new Vec3(pos.x, pos.y - 66, pos.z));
    }

    start() {

    }

    update(dt: number) {
        // const doorRoot3DWorldPos = this.camera.screenToWorld(this.ring.getWorldPosition());
        // console.log("doorRoot3DWorldPos is ", doorRoot3DWorldPos);
    }

    onEnable() {
        this.adapterCamera();
        input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
        input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
        input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);
        input.on(Input.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
    }

    onDisable() {
        input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
        input.off(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
        input.off(Input.EventType.TOUCH_END, this.onTouchEnd, this);
        input.off(Input.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
    }

    updateIdeaCount(idea: number) {

    }

    onTouchStart(event: EventTouch) {
        if (!this.camera) {
            console.log("摄像机为空");
            return;
        }
        const p = event.getLocation();
        // event.getUILocation
        let ray = new geometry.Ray();
        this.camera.screenPointToRay(p.x, p.y, ray);
        // this.slotsNode.enabled = false;
        audioManager.playEffect('audio/click');

        const targetOut = this._computeRayEnd(ray);
        const mask = 1 << 1 | 1 << 5 | 1 << 7;
        const maxDistance = 1000000;

        const rayCastClosetFunc = () => {
            const hasCast = PhysicsSystem.instance.raycastClosest(ray, mask, maxDistance);

            if (hasCast) {
                const res = PhysicsSystem.instance.raycastClosestResult;
                const colliderItem = res.collider;
                const rb1 = colliderItem.node.getComponent(RigidBody);

                // 只过滤玩具
                if (rb1.getGroup() == PhyGroup.TOYS || rb1.getGroup() == PhyGroup.IN || rb1.getGroup() == PhyGroup.FLY) {
                    Vec3.subtract(this._delta, this.node.worldPosition, res.hitPoint);
                    this.tapNode = colliderItem.node;
                    const toyComp = this.tapNode.getComponent(EliminateToy);
                    const scale = toyComp.originScale;
                    this.tapNode.setScale(toyComp.originScale);

                    if (!toyComp.canTouch) {
                        console.log("不能触摸了");
                        return;
                    }
                    toyComp.node['canClear'] = true;

                    const pos = new Vec3(res.hitPoint.x, this.y, res.hitPoint.z);
                    this.tapStartPos = this.tapNode.worldPosition.clone();

                    tween(this.tapNode).to(0.1, { worldPosition: pos, scale: scale.clone().multiplyScalar(1.2) }).start()

                    this._dragging = true;

                    // gameManager.game.lockNodeByName(this.tapNode.name, true);
                    const rb = this.tapNode.getComponent(RigidBody);
                    rb && (rb.useGravity = false);
                    // 添加扭矩
                    rb.applyTorque(new Vec3(-180, -180, -180));

                    if (rb.group != PhyGroup.IN) {
                        rb.group = PhyGroup.FLY;
                    }
                    this.touchStartTime = Date.now();
                    this.touchEndTime = 0;
                    return;
                } else {
                    console.log("不能点击碰撞组：", rb1.getGroup());
                }
            } else {
                console.log("射线检测没有检测到");
            }
        }

        const rayCastCloseByMatch3 = () => {
            const hasCast = PhysicsSystem.instance.raycastClosest(ray, mask, maxDistance);

            if (hasCast) {
                const res = PhysicsSystem.instance.raycastClosestResult;
                const colliderItem = res.collider;
                const rb1 = colliderItem.node.getComponent(RigidBody);
                // 只过滤玩具
                if (rb1.getGroup() == PhyGroup.TOYS) {
                    // 高亮显示
                    this.tapNode = colliderItem.node;
                    const toyComp = this.tapNode.getComponent(EliminateToy);

                    const curPos = this.tapNode.getPosition();
                    this.tapNode.setPosition(curPos.x, 300, curPos.z);
                }

            } else {
                console.log("射线检测没有检测到");
            }
        }
        if (eliminateGameManager.gameMode == EliminateMode.MATCH2) {
            // 二消逻辑
            rayCastClosetFunc();
        } else {
            // 关闭物理引擎
            // PhysicsSystem.instance.enable = true;
            // 三消逻辑
            rayCastCloseByMatch3();
        }
    }

    public updateLevelNumberLabel(level: number) {
        this.levelNumberLabel.string = level.toString();
    }

    public updateToolCountLabel(times: number, useAble: boolean) {
        this.idea.active = useAble;
        this.toolTimesLabel.string = times.toString();
    }

    private _computeRayEnd(ray: geometry.Ray) {
        const origin = ray.o.clone();
        let targetOut: Vec3 = new Vec3();
        Vec3.normalize(targetOut, ray.d);
        Vec3.scaleAndAdd(targetOut, origin, targetOut, 10000000);
        return targetOut;
    }

    onTouchMove(event: EventTouch) {
        if (eliminateGameManager.gameMode == EliminateMode.MATCH3) return;
        // 所有的拖动逻辑都已在 update() 中处理，所以这里不需要再做任何事情
        if (!this.camera) return;
        if (!this.tapNode) return;
        this.moveEvent = event;

        if (this.tapNode['clear']) return;
        const toyComp = this.tapNode.getComponent(EliminateToy);
        if (!toyComp.canTouch) {
            console.log("不能触摸了");
            return;
        }
        // 该节点被锁定了
        // if ((gameManager.game.canOptionUserId == gameManager.networkManager.userIdFormNode)) {
        // 自由自己能操作
        let targetPos: Vec3 = new Vec3();
        if (this._dragging && this.moveEvent && this.tapNode) {
            const rb = this.tapNode.getComponent(RigidBody);
            // 不使用重力
            rb.useGravity = false;

            this.tapNode.getComponent(Collider).enabled = true;
            let mousePos = this.moveEvent.getLocation();

            const mask = 1 << 2;
            const maxDis = 100000;

            let ray = new geometry.Ray();
            this.camera.screenPointToRay(mousePos.x, mousePos.y, ray);
            if (PhysicsSystem.instance.raycastClosest(ray, mask, maxDis)) {
                const raycastClosetResult = PhysicsSystem.instance.raycastClosestResult;
                const colliderItem = raycastClosetResult.collider;
                if (colliderItem.node.name == 'plane') {
                    const intersection = raycastClosetResult.hitPoint;
                    Vec3.subtract(this._delta, intersection, this.tapNode.position);
                    targetPos.x = intersection.x;
                    targetPos.y = this.y;
                    targetPos.z = intersection.z;
                    this.tapNode.setWorldPosition(targetPos);
                }
            }
        }
    }

    private _touchEndForMatch2(event: EventTouch) {
        if (!this.tapNode) return;
        if (this.tapNode['clear']) return;
        // if (gameManager.game.canOptionUserId == gameManager.networkManager.userIdFormNode) {
        const toyComp = this.tapNode.getComponent(EliminateToy);
        if (!toyComp.canTouch) {
            console.log("不能触摸了");
            return
        }
        // toyComp.node['canClear'] = false;
        let startPoint = event.getStartLocation();
        // 禁用客户端物理
        const rb = this.tapNode.getComponent(RigidBody);

        const scale = toyComp.originScale;
        this.tapNode.setScale(scale);

        rb.useGravity = true;
        if (rb.group != PhyGroup.IN) {
            rb.group = PhyGroup.TOYS;
        } else {
            this.slotsNode.moveToysToRightPosAndCheck();
        }

        this._dragging = false;

        const pos = event.getLocation();
        let lenVec = pos.clone().subtract(startPoint);

        if (Vec2.len(lenVec) < 15 && rb.group != PhyGroup.IN) {
            rb.group = PhyGroup.FLY;
            // 认为是原地点击没有产生move行为 移动到目标位置
            rb.useGravity = false;
            rb.setLinearVelocity(new Vec3(0));
            rb.setAngularVelocity(new Vec3(0));
            Tween.stopAllByTarget(this.tapNode);
            // rb.node.scale = rb.node['ori_scale'];

            // 向触发器
            tween(this.tapNode).to(0.5, { position: new Vec3(0, 30, 16) }).start();
            this.tapNode = null;
            this.moveEvent = null;
            this._dragging = false;
            return;
        }


        this.touchEndTime = Date.now();
        if (this.touchEndTime - this.touchStartTime < 150 && rb.group != PhyGroup.IN) {
            Tween.stopAllByTarget(this.tapNode);
            // rb.node.scale = rb.node['ori_scale'];
            const offset = event.getLocation().clone().subtract(event.getStartLocation()).normalize();
            this.tapNode.emit('click');
            rb && rb.applyForce((new Vec3(offset.x, 0, -offset.y).multiplyScalar(5000)));
        }
        // if (toyComp && toyComp.enterSlot) {

        // }
        // this.slotsNode.moveToysToTargetPos(this.slotsNode.boxs);

        this.tapNode = null;
        this.moveEvent = null;
    }

    /** 3消手指抬起逻辑 */
    private _touchEndForMatch3(event: EventTouch) {
        const clickPos = event.getLocation();
        let ray = new geometry.Ray();
        this.camera.screenPointToRay(clickPos.x, clickPos.y, ray);

        const mask = 1 << 2;
        const maxDistance = 1000000;
        const hasCast = PhysicsSystem.instance.raycastClosest(ray, mask, maxDistance);

        if (hasCast) {
            const hitRes = PhysicsSystem.instance.raycastClosestResult;
        }

        if (!this.tapNode) {
            return;
        }

        this.match3.eliminateCheck(this.tapNode);
        this.tapNode = null;
    }

    onTouchEnd(event: EventTouch) {
        if (eliminateGameManager.gameMode == EliminateMode.MATCH2) {
            this._touchEndForMatch2(event);
        } else {
            // 禁用底部墙壁的碰撞效果
            // const board = eliminateGameManager.game.boards.getChildByName('bottomBoardV');
            // board.getComponent(Collider).enabled = false;
            // board.getComponent(RigidBody).enabled = false;
            this._touchEndForMatch3(event);
        }
    }

    public btnEvents(event: any, data: any) {
        switch (data) {
            case "auto":
                console.log("自动消除");
                this.autoEliminate();
                break;
            case "exit":
                NDB.closeWebView();
                break;
            case "blur_bottom":
                this.renderTarget();
                break;
        }
    }

    public renderTarget() {
        let [w, h] = [Math.floor(view.getVisibleSize().width), Math.floor(view.getVisibleSize().height)];
        let renderTex = new RenderTexture();
        renderTex.initialize({
            name: "s",
            width: w,
            height: h,
        });
        this.UICamera.targetTexture = renderTex;

        let redTop = new RenderTexture();
        redTop.initialize({
            name: 'ss',
            width: w,
            height: h
        });

        let d3 = new RenderTexture();
        d3.initialize({
            name: "d3",
            width: w,
            height: h
        });

        this.camera.targetTexture = d3;
        this.toastCamera.targetTexture = redTop;

        this.scheduleOnce(() => {
            // renderTex.getPixelFormat()
            // renderTex
            // console.log("renderTex is ", renderTex);
            // this.gamePreview
            this.gamePreview.renderTextures(renderTex, d3, redTop);

            // let frame = new SpriteFrame();
            // frame.texture = d3;
            // frame.getGFXTexture();
            // this.topPreview.node.getComponent(UITransform).width = w / 2;
            // this.topPreview.node.getComponent(UITransform).height = h / 2;
            // this.topPreview.node.setScale(new Vec3(1, -1, 1));
            // this.topPreview.spriteFrame = frame;

            this.UICamera.targetTexture = null;
            this.camera.targetTexture = null;
            this.toastCamera.targetTexture = null;

        }, 0);

    }

    // 暂停游戏弹窗
    popPause() {
        let pauseNode = null;
        if (!this.node.getChildByName('pause')) {
            let pausePrefab = null;
            if (eliminateGameManager.gameMode == EliminateMode.MATCH2) {
                pausePrefab = this.pausePrefab;
            } else {
                pausePrefab = this.match3Pause;
            }
            pauseNode = instantiate(pausePrefab);
            pauseNode.name = "pause";
            pauseNode.setPosition(new Vec3(0));
            this.node.addChild(pauseNode);
        } else {
            pauseNode = this.node.getChildByName('pause');
            pauseNode.active = true;
        }
        if (pauseNode) {
            const content = pauseNode.getChildByName("content");
            const contentAnim = content.getComponent(Animation);
            contentAnim.play();
        }
    }

    autoEliminate() {
        if (eliminateGameManager.game.score >= eliminateConsts.auto_cost_score) {
            eliminateGameManager.useTool = true;
            // 减积分
            eliminateGameManager.game.score -= eliminateConsts.auto_cost_score;
            // 从物品堆里面找出一个物品
            const nodes = eliminateGameManager.game.findAtoyFromHeap(this.slotsNode.toysQueue);
            console.log("nodes is ", nodes);
            if (!nodes) {
                console.log("没有找到玩具");
                return;
            }

            nodes && nodes.forEach(item => {
                if (!item) return;
                item['canClear'] = true;
                const collider = item.getComponent(RigidBody);
                collider.group = PhyGroup.FLY;
                const pos = item.getWorldPosition();
                item.setWorldPosition(new Vec3(pos.x, 10, pos.z));
            });

            nodes && tween(nodes[0]).to(0.2, { position: new Vec3(0, 6, 16) }).call(() => {
                const collider = nodes[0].getComponent(RigidBody);
                // collider && (collider.enabled = false);

            }).start();
            if (nodes.length > 1) {
                tween(nodes[1]).to(0.2, { position: new Vec3(0, 6, 16) }).call(() => {
                    const collider = nodes[1].getComponent(RigidBody);
                    // collider && (collider.enabled = false);
                }).start();
            }
        } else {
            CommonToastManager.toast(0.8, "Score is not enough!", eliminateGameManager.game.toastPrefab);
        }
    }

    /**
     * 更新分数
     * @param  {number} score
     */
    public updateScore(score: number) {
        const curVal = +this.scoreLabel.string;
        tweenLabelString(curVal, score, this.scoreLabel, 0.3);
    }

    /** 消除的时候开门 */
    public async openDoor(open: boolean, time: number = 0.25): Promise<void> {
        return new Promise((resolve, reject) => {
            const animation = this.ring.getComponent(Animation);
            animation.play();
            const state: AnimationState = animation.getState('open_door');
            if (open) {
                state.wrapMode = AnimationClip.WrapMode.Normal;
            } else {
                state.wrapMode = AnimationClip.WrapMode.Reverse;
            }
            animation.on(Animation.EventType.FINISHED, resolve, this);
        });
    }

    public updateTimesLabel(times: number | string) {
        if (eliminateGameManager.gameMode == EliminateMode.MATCH2) {
            this.timesLabel.string = `x${times.toString()}`;
        } else {
            this.match3.updateTimesLabel(times);
        }
    }

    /**
     * 显示结算界面
     */
    showResult(isWin: boolean, score: number) {
        if (this.node.getChildByName('resultRoot')) {
            const resultRootNode = this.node.getChildByName("resultRoot");
            resultRootNode.destroy();
        }

        const node = instantiate(this.resultPrefab);
        node.name = 'resultRoot';
        node.setPosition(new Vec3(0));

        const resultComp = node.getComponent(EliminateResult);
        this.node.addChild(node);
        resultComp.showToast(isWin, score);
    }
}

